/*
 * JNIObject.cpp  0.4.0 / Nov 14, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
#include "JNIObject.h"

#include "JNIWrapper.h"

// JNIObject :: Public Constructor. --------------------------------------------

/*!
 * \brief Constructs new JNIObject object.
 *
 * \param env the JNIEnv pointer
 * \param obj the Java object
 */
JNIObject::JNIObject(JNIEnv *env, jobject obj)
  : m_env(env), m_ref(JNIWrapper::newWeakGlobalRef(env, obj))
{
  Q_ASSERT(m_ref);
}

// JNIObject :: Public Destructor. ---------------------------------------------

/*!
 * \brief Destroys JNIObject object.
 */
JNIObject::~JNIObject()
{
  if (m_ref) {
    JNIWrapper::deleteWeakGlobalRef(m_env, m_ref);
  }
}

// JNIObject :: Private Constructor. -------------------------------------------

JNIObject::JNIObject(const JNIObject &)
{
  // copy constructor is disabled.
}

// JNIObject :: Public Member Functions. ---------------------------------------

/*!
 * \brief Returns \c true if the JNI object is alive (not collected).
 *
 * \return \c true if if the JNI object is alive
 */
bool JNIObject::isLive()
{
  return JNIWrapper::isLiveRef(m_env, m_ref);
}

/*!
 * \brief Checks for JNI exceptions.
 */
void JNIObject::checkException()
{
  JNIWrapper::checkException(m_env);
}

/*!
 * \brief Test if an exception has occurred.
 *
 * \return \c true if the exception has occurred
 */
bool JNIObject::testException()
{
  return JNIWrapper::testException(m_env);
}

/*!
 * \brief Prints the error message and terminates virtual machine.
 *        <p>
 *          NOTE: This method does not return.
 *        </p>
 *
 * \param errorMessage the error message
 */
void JNIObject::fatalError(const char *errorMessage)
{
  JNIWrapper::fatalError(m_env, errorMessage);
}

/*!
 * \brief Throws java's internal error.
 *
 * \param errorMessage the error message
 */
void JNIObject::throwInternalError(const char *errorMessage)
{
  JNIWrapper::throwInternalError(m_env, errorMessage);
}

/*!
 * \brief Throws java's out of memory error.
 *
 * \param errorMessage the error message
 */
void JNIObject::throwOutOfMemoryError(const char *errorMessage)
{
  JNIWrapper::throwOutOfMemoryError(m_env, errorMessage);
}

/*!
 * \brief Throws java's runtime exception.
 *
 * \param exceptionMessage the exception message
 */
void JNIObject::throwRuntimeExcpetion(const char *exceptionMessage)
{
  JNIWrapper::throwRuntimeExcpetion(m_env, exceptionMessage);
}

/*!
 * \brief Returns the fieldID.
 *
 * \param name the field name
 * \param sig the field signature
 *
 * \return the fieldID
 */
jfieldID JNIObject::getFieldID(const char *name, const char *sig)
{
  return JNIWrapper::getFieldID(m_env, getObjectClass(), name, sig);
}

/*!
 * \brief Returns the jmethodID.
 *
 * \param name the method name
 * \param sig the method signature
 *
 * \return the jmethodID
 */
jmethodID JNIObject::getMethodID(const char *name, const char *sig)
{
  return JNIWrapper::getMethodID(m_env, getObjectClass(), name, sig);
}

/*!
 * \brief Returns the value of the object field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the object field
 */
jobject JNIObject::getObjectField(jfieldID fieldID)
{
  return JNIWrapper::getObjectField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the object field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setObjectField(jfieldID fieldID, jobject val)
{
  JNIWrapper::setObjectField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the boolean field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the boolean field
 */
jboolean JNIObject::getBooleanField(jfieldID fieldID)
{
  return JNIWrapper::getBooleanField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the boolean field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setBooleanField(jfieldID fieldID, jboolean val)
{
  JNIWrapper::setBooleanField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the byte field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the byte field
 */
jbyte JNIObject::getByteField(jfieldID fieldID)
{
  return JNIWrapper::getByteField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the byte field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setByteField(jfieldID fieldID, jbyte val)
{
  JNIWrapper::setByteField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the char field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the char field
 */
jchar JNIObject::getCharField(jfieldID fieldID)
{
  return JNIWrapper::getCharField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the char field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setCharField(jfieldID fieldID, jchar val)
{
  JNIWrapper::setCharField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the short field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the short field
 */
jshort JNIObject::getShortField(jfieldID fieldID)
{
  return JNIWrapper::getShortField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the short field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setShortField(jfieldID fieldID, jshort val)
{
  JNIWrapper::setShortField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the int field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the int field
 */
jint JNIObject::getIntField(jfieldID fieldID)
{
  return JNIWrapper::getIntField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the int field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setIntField(jfieldID fieldID, jint val)
{
  JNIWrapper::setIntField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the long field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the long field
 */
jlong JNIObject::getLongField(jfieldID fieldID)
{
  return JNIWrapper::getLongField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the long field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setLongField(jfieldID fieldID, jlong val)
{
  JNIWrapper::setLongField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the float field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the float field
 */
jfloat JNIObject::getFloatField(jfieldID fieldID)
{
  return JNIWrapper::getFloatField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the float field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setFloatField(jfieldID fieldID, jfloat val)
{
  JNIWrapper::setFloatField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns the value of the double field.
 *
 * \param fieldID the field ID
 *
 * \return the value of the double field
 */
jdouble JNIObject::getDoubleField(jfieldID fieldID)
{
  return JNIWrapper::getDoubleField(m_env, m_ref, fieldID);
}

/*!
 * \brief Sets the value of the double field.
 *
 * \param fieldID the field ID
 * \param val the new value
 */
void JNIObject::setDoubleField(jfieldID fieldID, jdouble val)
{
  JNIWrapper::setDoubleField(m_env, m_ref, fieldID, val);
}

/*!
 * \brief Returns JNI object class.
 *
 * \return JNI object class
 */
jclass JNIObject::getObjectClass()
{
  return m_env->GetObjectClass(m_ref);
}

/*!
 * \brief Calls JNI object method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callObjectMethod(jobject &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callObjectMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI boolean method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callBooleanMethod(jboolean &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callBooleanMethod(m_env, result, m_ref, methodID,
                                           args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI byte method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callByteMethod(jbyte &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callByteMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI char method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callCharMethod(jchar &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callCharMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI short method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callShortMethod(jshort &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callShortMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI int method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callIntMethod(jint &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callIntMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI long method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callLongMethod(jlong &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callLongMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI float method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callFloatMethod(jfloat &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callFloatMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI doble method.
 *
 * \param result the result
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callDoubleMethod(jdouble &result, jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callDoubleMethod(m_env, result, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Calls JNI void method.
 *
 * \param methodID the method ID
 * \param ... the method arguments
 *
 * \return \c true if no exception is thrown
 */
bool JNIObject::callVoidMethod(jmethodID methodID, ...)
{
  Q_ASSERT(methodID);
  va_list args;
  va_start(args, methodID);
  bool ret = JNIWrapper::callVoidMethod(m_env, m_ref, methodID, args);
  va_end(args);
  return ret;
}

/*!
 * \brief Returns jstring representation of the specified object.
 *
 * \return jstring representation of the specified object
 */
jstring JNIObject::toJString()
{
  return JNIWrapper::toString(m_env, m_ref);
}

/*!
 * \brief Creates new java string.
 *
 * \param uchars the unicode char array
 * \param len the length of the char array
 *
 * \return new Java string object
 */
jstring JNIObject::newJString(const jchar *uchars, jsize len)
{
  return JNIWrapper::newString(m_env, uchars, len);
}

/*!
 * \brief Creates new java string.
 *
 * \param bytes the UTF-8 char array
 *
 * \return new Java string object
 */
jstring JNIObject::newJStringUTF(const char *bytes)
{
  return JNIWrapper::newStringUTF(m_env, bytes);
}
